
#include "stdafx.h"

#include "stdafx.h"
#include <windows.h>
#include <mmdeviceapi.h>
#include <functiondiscoverykeys.h>  // PKEY_Device_FriendlyName
#include <endpointvolume.h>
#include "..\common.h"


#define EXIT_ON_ERROR(hres)	if (FAILED(hres))	{ goto Exit; }
#define SAFE_RELEASE(punk)	if ((punk) != NULL)	{ (punk)->Release(); (punk) = NULL; }

#define	MAX_VOLUME			100


void setVolume(float fRender, float fCapture)
{
	HRESULT hr;
	IMMDeviceEnumerator *pEnumerator = NULL;
	IMMDeviceCollection *pCollection = NULL;
	IMMDevice *pDevice = NULL;
	IPropertyStore *pProps = NULL;
	PROPVARIANT varName;
	IMMEndpoint *pEndpoint = NULL;
	EDataFlow DataFlow;
	IAudioEndpointVolume *pVolume = NULL;
	UINT uCount, i;
	float fLevel;

	hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (LPVOID *)&pEnumerator);
	EXIT_ON_ERROR(hr);

	// eRender, eCapture, eAll
	hr = pEnumerator->EnumAudioEndpoints(eAll, DEVICE_STATE_ACTIVE, &pCollection);
	EXIT_ON_ERROR(hr);
	SAFE_RELEASE(pEnumerator);

	hr = pCollection->GetCount(&uCount);
	EXIT_ON_ERROR(hr);
	for (i=0; i<uCount; i++)
	{
		hr = pCollection->Item(i, &pDevice);
		EXIT_ON_ERROR(hr);

		hr = pDevice->OpenPropertyStore(STGM_READ, &pProps);
		EXIT_ON_ERROR(hr);

		PropVariantInit(&varName);
		hr = pProps->GetValue(PKEY_Device_FriendlyName, &varName);
		EXIT_ON_ERROR(hr);
#ifdef	UNICODE
		if (NULL != _tcsstr(varName.pwszVal, USB_SOUND_STR))
#else
		{
			char szTextA[MAX_PATH];
			int nLen = WideCharToMultiByte(CP_ACP, 0, varName.pwszVal, -1, szTextA, MAX_PATH, NULL, NULL);
			szTextA[nLen] = NULL;
			if (NULL != _tcsstr(szTextA, USB_SOUND_STR))
				fLevel = 1.;
		}
		if (1. == fLevel)
#endif
		{
			hr = pDevice->QueryInterface(__uuidof(IMMEndpoint), (void **)&pEndpoint);
			EXIT_ON_ERROR(hr);

			hr = pEndpoint->GetDataFlow(&DataFlow);
			EXIT_ON_ERROR(hr);
			if (eRender == DataFlow)
				fLevel = fRender;
			else if (eCapture == DataFlow)
				fLevel = fCapture;

			hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (LPVOID *)&pVolume);
			EXIT_ON_ERROR(hr);

			hr = pVolume->SetMasterVolumeLevelScalar((fLevel / MAX_VOLUME), NULL);
			EXIT_ON_ERROR(hr);
		}
		PropVariantClear(&varName);
		SAFE_RELEASE(pVolume);
		SAFE_RELEASE(pEndpoint);
		SAFE_RELEASE(pProps);
		SAFE_RELEASE(pDevice);
	}

Exit:
	SAFE_RELEASE(pVolume);
	SAFE_RELEASE(pEndpoint);
	SAFE_RELEASE(pProps);
	SAFE_RELEASE(pDevice);
	SAFE_RELEASE(pCollection);
	SAFE_RELEASE(pEnumerator);
}
